#include <iostream>
#include <functional>
using namespace std;
namespace Jaxsen
{
    template <class T>
    class shared_ptr
    {
    public:
        shared_ptr(T *ptr) 
        : ptr_(ptr), count_(new size_t(1))
        {
        }

        template <class D>
        shared_ptr(T *ptr, D del) 
        : ptr_(ptr), count_(new size_t(1)), del_(del)
        {
        }

        shared_ptr(const shared_ptr<T> &sp)
            : ptr_(sp.ptr_), count_(sp.count_), del_(sp.del_)
        {
        }

        shared_ptr<T> &operator=(const shared_ptr<T> &sp)
        {
            // 情况1：自己对自己赋值
            if (sp.ptr_ == ptr_)
            {
                return *this;
            }
            release();
            ptr_ = sp.ptr_;
            count_ = sp.count_;
            ++(*count_);
            return *this;
        }

        T &operator*()
        {
            return *ptr_;
        }

        T *operator->()
        {
            return ptr_;
        }

        void release()
        {
            if ((*count_) == 1)
            {
                del_(ptr_);
                // delete ptr_;
                delete count_;
            }
            else
            {
                --(*count_);
            }
        }

        ~shared_ptr()
        {
            cout << "析构了" << endl;
            release();
        }

    private:
        T *ptr_;
        size_t *count_;
        function<void(T *ptr)> del_  = [](T *ptr){ delete ptr; };
    };
}